import { Commit, createStore } from 'vuex'
// import { testData, testPosts, ColumnProps, PostProps } from '@/selfFunction/testData'
import axios, { AxiosRequestConfig } from 'axios'
import { objToArr, arrToObj } from '@/selfFunction/helper'

// eslint-disable-next-line @typescript-eslint/ban-types
export interface ResponseType<P = {}> {
  code: number
  msg: string
  data: P
}

export interface ImageProps {
  _id?: string
  url?: string
  createAt?: string
  fitUrl?: string
}

export interface ListData {
  author: string
  avatar?: {
    _id: string
    url: string
  }
  createdAt?: string
  description: string
  featured?: boolean
  title: string
  key?: number
  __v?: number
  _id: string
}

export interface UserProps {
  isLogin: boolean
  nickName: string
  _id?: string
  column?: number
  email?: string
  avatar?: ImageProps
  columnId?: number
}

export interface ColumnProps {
  _id: string
  title: string
  avatar?: ImageProps
  description: string
}

export interface PostProps {
  _id?: string;
  title: string;
  excerpt?: string;
  content?: string;
  image?: ImageProps | string;
  createdAt?: string;
  column?: string | number;
  author?: string | UserProps;
  isHTML?: boolean;
  avatar?: {
    _id: string
    url: string
  }
  key?: number
  __v?: number
  description: string
  featured: boolean
  columnId: number | undefined
}

export interface GlobalErrorProps {
  status: boolean
  message?: string
}

interface ListProps<P> {
  [id: string]: P;
}

export interface AccountProps {
  name: string
  sex: string
  birth: string
}

export interface GlobalDataProps {
  error: GlobalErrorProps
  token: string
  loading: boolean
  columns: { data: ListProps<ColumnProps>; currentPage: number; total: number }
  posts: { data: ListProps<PostProps>; loadedColumns: string[] }
  user: UserProps
  account: AccountProps
}

const getAndCommit = async (url: string, mutationName: string,
  commit: Commit, config: AxiosRequestConfig = { method: 'get' }, extraData?: any) => {
  const { data } = await axios(url, config)
  if (extraData) {
    commit(mutationName, {
      data,
      extraData
    })
  } else {
    commit(mutationName, data)
  }
  return data
}

const postAndCommit = async (url: string, mutationName: string, commit: Commit,
  config: AxiosRequestConfig = { method: 'get' }, extraData?: any) => {
  const { data } = await axios.get(url, config)
  // console.log(data)
  if (extraData) {
    commit(mutationName, {
      data,
      extraData
    })
  } else {
    commit(mutationName, data)
  }
  return data
}

const moduleA = {
  state: {},
  actions: {},
  mutations: {}
}

export default createStore<GlobalDataProps>({
  state: {
    error: {
      status: false,
      message: ''
    },
    token: localStorage.getItem('token') || '',
    loading: false,
    columns: {
      data: {},
      currentPage: 0,
      total: 0
    },
    posts: {
      data: {},
      loadedColumns: []
    },
    user: {
      isLogin: false,
      nickName: 'TENDOUZHI',
      columnId: 5
    },
    account: {
      name: 'TENDOUZHI',
      sex: '男',
      birth: '2002-11-23'
    }
  },
  mutations: {
    creatPost (state, newPost) {
      state.posts.data[newPost._id] = newPost
      console.log(1)
      console.log(state.posts.data)
    },
    fetchColumns (state, rawData) {
      const { data } = state.columns
      const {
        list,
        count,
        currentPage
      } = rawData.data
      state.columns = {
        data: { ...data, ...arrToObj(list) },
        total: count,
        currentPage: currentPage * 1
      }
    },
    fetchColumn (state, rawData) {
      state.columns.data[rawData.data._id] = rawData.data
    },
    fetchPosts (state, rawData) {
      state.posts = rawData.data.list
    },
    deletePost (state, { data }) {
      delete state.posts.data[data._id]
    },
    setLoading (state, status) {
      state.loading = status
    },
    setError (state, e: GlobalErrorProps) {
      state.error = e
    },
    fetchCurrentUser (state, rawData) {
      state.user = { isLogin: true, ...rawData.data }
    },
    login (state, rawData) {
      const { token } = rawData
      state.token = token
      localStorage.setItem('token', token)
      // axios.defaults.headers.common.Authorization = `Bearer ${token}`
    },
    logout (state) {
      state.user.isLogin = false
      state.token = ''
      localStorage.removeItem('token')
      delete axios.defaults.headers.common.Authorization
    },
    addNewPosts (state) {
      axios.get('/mock/columns').then(({ data }: ListProps<any>) => {
        state.columns.data = data.data.list
      })
    },
    editInfo (state, account) {
      axios.post('/mock/edit', account).then(({ data }) => {
        data = data.account
        state.account.name = data.name
        state.account.sex = data.sex
        state.account.birth = data.birth
      })
    }
  },
  actions: {
    fetchColumns ({ commit }) {
      return getAndCommit('/columns', 'fetchColumns', commit)
    },
    fetchColumn ({ commit }, cid) {
      return getAndCommit(`/columns/${cid}`, 'fetchColumn', commit)
    },
    fetchPosts ({ commit }, cid) {
      return getAndCommit(`/columns/${cid}/posts`, 'fetchPosts', commit)
    },
    fetchCurrentUser ({ commit }) {
      // return getAndCommit('/user/current', 'fetchCurrentUser', commit)
      const loginData = {
        data: {
          column: {
            _id: '',
            avatar: {
              utl: ''
            },
            title: '',
            description: ''
          },
          nickName: 'TENDOUZHI'
        }
      }
      commit('fetchCurrentUser', loginData)
    },
    login ({ commit }, payLoad) {
      return postAndCommit('/mock/login', 'login', commit, {
        method: 'post',
        data: payLoad
      })
    },
    logout ({ commit }) {
      commit('logout')
    },
    createPost ({ commit }, payLoad) {
      return postAndCommit('/mock/columns', 'creatPost', commit, {
        method: 'post',
        data: payLoad
      })
    },
    deletePost ({ commit }, id) {
      return postAndCommit(`/posts/${id}`, 'deletePost', commit, { method: 'delete' })
    },
    loginAndFetch ({ dispatch }, loginData) {
      return dispatch('login', loginData).then(() => {
        return dispatch('fetchCurrentUser')
      })
    },
    addNewPosts ({ commit }) {
      commit('addNewPosts')
    },
    editInfo ({ commit }, account) {
      commit('editInfo', account)
    }
  },
  modules: {
    a: moduleA
  },
  getters: {
    getColumns: (state) => {
      return objToArr(state.columns.data)
    },
    getColumnById: (state) => (id: string) => {
      // axios.get('/mock/columns').then(({ data }: ListProps<any>) => {
      //   state.columns.data = data.data.list
      // })
      // console.log('getColumnById:', state.columns.data[id])
      return state.columns.data[id]
    },
    getPostsByCid: (state) => (cid: string) => {
      return objToArr(state.posts.data).filter(post => post.column === cid)
    }
  }
})
